package org.example.seckill.util;

/**
 * @author woopsion
 * @date 2025-06-29
 */

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

/**
 * Cookie操作工具类 - 支持UTF-8编码、安全配置、路径控制等
 */
public class CookieUtils {

    /**
     * 默认Cookie路径 (应用根路径)
     */
    private static final String DEFAULT_PATH = "/";

    /**
     * 默认Cookie有效期 (7天)
     */
    private static final int DEFAULT_MAX_AGE = 7 * 24 * 60 * 60;

    /**
     * 默认字符编码 (UTF-8)
     */
    private static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name();

    /**
     * 设置Cookie（使用默认配置 + UTF-8编码）
     *
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值（自动UTF-8编码）
     */
    public static void setCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, DEFAULT_MAX_AGE, DEFAULT_PATH, false, false);
    }

    /**
     * 设置自定义Cookie（自动UTF-8编码）
     *
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值（自动UTF-8编码）
     * @param maxAge   有效期(秒)，-1表示浏览器关闭失效
     * @param path     Cookie路径
     * @param httpOnly 是否禁止JS访问
     * @param secure   是否仅HTTPS传输
     */
    public static void setCookie(HttpServletResponse response, String name, String value,
                                 int maxAge, String path, boolean httpOnly, boolean secure) {
        try {
            // 对值进行UTF-8编码
            String encodedValue = URLEncoder.encode(value, DEFAULT_ENCODING);
            Cookie cookie = new Cookie(name, encodedValue);
            cookie.setMaxAge(maxAge);
            cookie.setPath(path != null ? path : DEFAULT_PATH);
            cookie.setHttpOnly(httpOnly);
            cookie.setSecure(secure);
            response.addCookie(cookie);
        } catch (Exception e) {
            // UTF-8编码通常不会出错，此处做安全回退
            throw new IllegalArgumentException("Cookie value encoding failed", e);
        }
    }

    /**
     * 获取Cookie值（自动UTF-8解码）
     *
     * @param request HttpServletRequest
     * @param name    Cookie名称
     * @return Optional包装的Cookie值（自动UTF-8解码）
     */
    public static String getCookie(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) return null;

        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(name)) {
                return decodeCookieValue(cookie.getValue());
            }
        }
        return null;
    }

    /**
     * 安全删除Cookie（使用默认路径）
     *
     * @param response HttpServletResponse
     * @param name     Cookie名称
     */
    public static void deleteCookie(HttpServletResponse response, String name) {
        deleteCookie(response, name, DEFAULT_PATH);
    }

    /**
     * 删除指定路径的Cookie
     *
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param path     Cookie路径
     */
    public static void deleteCookie(HttpServletResponse response, String name, String path) {
        Cookie cookie = new Cookie(name, null);
        cookie.setMaxAge(0); // 立即过期
        cookie.setPath(path != null ? path : DEFAULT_PATH);
        response.addCookie(cookie);
    }

    /**
     * 设置安全Cookie（防XSS和CSRF + UTF-8编码）
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值（自动UTF-8编码）
     */
    public static void setSecureCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, DEFAULT_MAX_AGE, DEFAULT_PATH, true, true);
    }

    /**
     * 设置会话级Cookie（浏览器关闭失效 + UTF-8编码）
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值（自动UTF-8编码）
     */
    public static void setSessionCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, -1, DEFAULT_PATH, true, false);
    }

    /**
     * 设置跨域Cookie（需谨慎使用 + UTF-8编码）
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值（自动UTF-8编码）
     * @param domain   域名（如 ".example.com"）
     */
    public static void setCrossDomainCookie(HttpServletResponse response, String name,
                                            String value, String domain) {
        try {
            String encodedValue = URLEncoder.encode(value, DEFAULT_ENCODING);
            Cookie cookie = new Cookie(name, encodedValue);
            cookie.setMaxAge(DEFAULT_MAX_AGE);
            cookie.setPath(DEFAULT_PATH);
            cookie.setHttpOnly(true);
            cookie.setSecure(true);
            cookie.setDomain(domain);
            response.addCookie(cookie);
        } catch (Exception e) {
            throw new IllegalArgumentException("Cookie value encoding failed", e);
        }
    }

    /**
     * 对Cookie值进行UTF-8解码
     * @param encodedValue 编码后的Cookie值
     * @return 解码后的原始值
     */
    private static String decodeCookieValue(String encodedValue) {
        if (encodedValue == null) return null;

        try {
            // 双重解码处理浏览器自动解码的情况
            String decoded = URLDecoder.decode(encodedValue, DEFAULT_ENCODING);

            // 检查是否被浏览器自动解码过（包含%说明需要二次解码）
            if (decoded.contains("%")) {
                return URLDecoder.decode(decoded, DEFAULT_ENCODING);
            }
            return decoded;
        } catch (Exception e) {
            // 解码失败时返回原始值
            return encodedValue;
        }
    }
}